# Copyright 2009 http://www.yuntien.com
# Licensed under the Apache License, Version 2.0

from google.appengine.api import users
from google.appengine.api import memcache

KEY_PAGE = 'PAGE_' 
COMMON_TIME_OUT = 3600

def check_page_cache_hook(request, *args, **kwds):
    if getattr(request, '_bypass_cache', None):
        return False
    
    #only use cache for anonymous user
    if users.get_current_user():
        return False
    
    if request.method != 'GET':
        return False
    
    return True    

def check_page_cache(always=False, timeout=COMMON_TIME_OUT, with_host=True, check_hook=check_page_cache_hook):
    def decorator(method):
        def new_method(request, *args, **kwds):
            
            if check_hook and check_hook(request, *args, **kwds) == False and not always:
                return method(request, *args, **kwds)
        
            if with_host:
                key = KEY_PAGE + request.build_absolute_uri()
            else:
                key = KEY_PAGE + request.get_full_path()
    
            #try to fetch data from cache
            try:
                response = memcache.get(key)
            except:
                response = None

            if response is not None:
                return response

            response = method(request, *args, **kwds)
            
            #only cache valid response
            if not response.status_code == 200:
                return response
            
            #try to fill data to cache
            try:
                memcache.set(key, response, timeout)
            finally:
                return response            
        return new_method
    return decorator

#check cache by cache key
def check_cache(key, timeout=COMMON_TIME_OUT):
    def decorator(method):
        def new_method(*args, **kwds):
            #try to fetch data from cache
            try:
                response = memcache.get(key)
            except:
                response = None

            if response is not None:
                return response

            response = method(*args, **kwds)
            
            #try to fill data to cache
            try:
                memcache.set(key, response, timeout)
            finally:
                return response            
        return new_method
    return decorator

#cache decorator
def delete_cache(key):
    def decorator(method):
        def new_method(self, *args, **kwds):
            response = method(self, *args, **kwds)
            memcache.delete(key)
            return response        
        return new_method
    return decorator

#cache decorator
def delete_all_cache(method):
    def new_method(self, *args, **kwds):
        response = method(self, *args, **kwds)
        memcache.flush_all()
        return response
    return new_method
